import { Injectable } from '@nestjs/common';
import { CreateTestDTO } from '@src/dtos/test/createTest.dto'
import { Test } from '@src/common/entities/test.entity';
import { RedisClient } from '@src/common/providers/redisClient.service';
import { getManager, Transaction, TransactionRepository } from "typeorm"
import { TestDao } from "@src/daos/test.dao"

@Injectable()
export class TestService {
   constructor(
      private readonly testDao: TestDao,
      private readonly redis: RedisClient,
   ) {

   }
   private readonly test: CreateTestDTO;

   setLog(text) {
      console.log('发起了', text, '请求')
   }

   // 测试事务
   async testTransac(data: any) {
      // console.log(data)
      return getManager().transaction(async transactionalEntityManager => {
         return await transactionalEntityManager.findOne<Test>(Test, { id: data.id });
      }).then(res => {
         console.log('tranction done.')
         return res
      }).catch(Error => {
         console.log('tranction failed, ' + Error)
         return 'tranction failed, ' + Error;
      })
      // return await this.TestRepository.findOne({
      //    where: { id: id },
      //    cache: false
      // })
   }

   async findOne(id) {
      this.setLog('findOne')

      let data = await this.redis.client.get('id_' + id)

      if (!data) {
         data = await this.testDao.getOneTestFromDB(id)

         await this.redis.client.set('id_' + id, JSON.stringify(data))

         return Promise.resolve({
            from: 'database',
            data
         })
      } else {
         let newData = await this.testDao.getOneTestFromDB(id)

         let oldData = JSON.parse(data)

         if (newData.updatedAt != oldData.updatedAt) {

            data = newData
            await this.redis.client.set('id_' + id, JSON.stringify(data))
            return Promise.resolve({
               from: 'database',
               data
            })
         } else {
            return Promise.resolve({
               from: 'redis',
               data: JSON.parse(data)
            })
         }

      }
   }

   async createOne(createCatDto: CreateTestDTO) {
      this.setLog('createOne')

      getManager().transaction(async manager => {
         return await this.testDao.saveOneTest(manager, createCatDto)
      }).then(res => {
         console.log('tranction done.')
         return res
      }).catch(Error => {
         console.log('tranction failed, ' + Error)
         throw "tranction failed.";
      })

      return Promise.resolve({
         success: 200
      });
   }

   async updateOne(test: Test) {
      this.setLog('updateOne')

      let testObj = await this.testDao.getOneTestFromDB(test.id)

      // await this.testDao.saveOneTest()
      getManager().transaction(async manager => {
         let res = await this.testDao.saveOneTest(manager, {
            id: testObj.id,
            name: test.name,
            description: test.description,
            filename: test.filename,
            views: test.views,
            isPublished: test.isPublished
         })
         console.log("结果：", res)

         return res

      }).then(res => {
         console.log('tranction done.')
         return res
      }).catch(Error => {
         console.log('tranction failed, ' + Error)
         throw "tranction failed.";
      })

      return Promise.resolve({
         success: 200
      });
   }

   async deleteOne(id) {
      this.setLog('deleteOne')

      let testObj = await this.testDao.getOneTestFromDB(id)
      // await this.testDao.deleteOneTestFromDB(testObj)
      getManager().transaction(async manager => {
         await this.testDao.deleteOneTestFromDB(manager, testObj)
      }).then(res => {
         console.log('tranction done.')
         return res
      }).catch(Error => {
         console.log('tranction failed, ' + Error)
         throw "tranction failed.";
      })

      await this.testDao.deleteOneTestFromRedis(id)

      return Promise.resolve({
         success: 200
      });
   }
}